package com.kexio.common.utils;

import com.kexio.common.constants.CommonConstants;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.regex.Pattern;

/**
 * 字符串工具类
 * 
 * 提供常用的字符串处理方法
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
public final class StringUtils {
    
    // ==================== 常用正则表达式 ====================
    
    /** 手机号正则 */
    private static final Pattern MOBILE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
    
    /** 邮箱正则 */
    private static final Pattern EMAIL_PATTERN = Pattern.compile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
    
    /** 身份证号正则 */
    private static final Pattern ID_CARD_PATTERN = Pattern.compile("^\\d{17}[\\dXx]$");
    
    /** 中文字符正则 */
    private static final Pattern CHINESE_PATTERN = Pattern.compile("[\\u4e00-\\u9fa5]");
    
    // ==================== 私有构造函数 ====================
    
    private StringUtils() {
        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
    }
    
    // ==================== 基础判断方法 ====================
    
    /**
     * 判断字符串是否为空（null 或 空字符串）
     * 
     * @param str 字符串
     * @return 是否为空
     */
    public static boolean isEmpty(String str) {
        return str == null || str.isEmpty();
    }
    
    /**
     * 判断字符串是否非空
     * 
     * @param str 字符串
     * @return 是否非空
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }
    
    /**
     * 判断字符串是否为空白（null、空字符串或只包含空白字符）
     * 
     * @param str 字符串
     * @return 是否为空白
     */
    public static boolean isBlank(String str) {
        return str == null || str.trim().isEmpty();
    }
    
    /**
     * 判断字符串是否非空白
     * 
     * @param str 字符串
     * @return 是否非空白
     */
    public static boolean isNotBlank(String str) {
        return !isBlank(str);
    }
    
    /**
     * 判断字符串是否有文本内容
     * 
     * @param str 字符串
     * @return 是否有文本内容
     */
    public static boolean hasText(String str) {
        return isNotBlank(str);
    }
    
    // ==================== 默认值方法 ====================
    
    /**
     * 如果字符串为空则返回默认值
     * 
     * @param str 字符串
     * @param defaultValue 默认值
     * @return 结果字符串
     */
    public static String defaultIfEmpty(String str, String defaultValue) {
        return isEmpty(str) ? defaultValue : str;
    }
    
    /**
     * 如果字符串为空白则返回默认值
     * 
     * @param str 字符串
     * @param defaultValue 默认值
     * @return 结果字符串
     */
    public static String defaultIfBlank(String str, String defaultValue) {
        return isBlank(str) ? defaultValue : str;
    }
    
    // ==================== 转换方法 ====================
    
    /**
     * 安全地转换为字符串
     * 
     * @param obj 对象
     * @return 字符串表示
     */
    public static String toString(Object obj) {
        return obj == null ? CommonConstants.EMPTY : obj.toString();
    }
    
    /**
     * 安全地转换为字符串，空值返回默认值
     * 
     * @param obj 对象
     * @param defaultValue 默认值
     * @return 字符串表示
     */
    public static String toString(Object obj, String defaultValue) {
        return obj == null ? defaultValue : obj.toString();
    }
    
    // ==================== 截取和填充方法 ====================
    
    /**
     * 左填充字符串到指定长度
     * 
     * @param str 原字符串
     * @param size 目标长度
     * @param padChar 填充字符
     * @return 填充后的字符串
     */
    public static String leftPad(String str, int size, char padChar) {
        if (str == null) {
            str = CommonConstants.EMPTY;
        }
        
        int pads = size - str.length();
        if (pads <= 0) {
            return str;
        }
        
        char[] padding = new char[pads];
        Arrays.fill(padding, padChar);
        return new String(padding) + str;
    }
    
    /**
     * 右填充字符串到指定长度
     * 
     * @param str 原字符串
     * @param size 目标长度
     * @param padChar 填充字符
     * @return 填充后的字符串
     */
    public static String rightPad(String str, int size, char padChar) {
        if (str == null) {
            str = CommonConstants.EMPTY;
        }
        
        int pads = size - str.length();
        if (pads <= 0) {
            return str;
        }
        
        char[] padding = new char[pads];
        Arrays.fill(padding, padChar);
        return str + new String(padding);
    }
    
    /**
     * 截取字符串，超长时添加省略号
     * 
     * @param str 原字符串
     * @param maxLength 最大长度
     * @return 截取后的字符串
     */
    public static String truncate(String str, int maxLength) {
        return truncate(str, maxLength, "...");
    }
    
    /**
     * 截取字符串，超长时添加指定后缀
     * 
     * @param str 原字符串
     * @param maxLength 最大长度
     * @param suffix 后缀
     * @return 截取后的字符串
     */
    public static String truncate(String str, int maxLength, String suffix) {
        if (isEmpty(str) || str.length() <= maxLength) {
            return str;
        }
        
        if (suffix == null) {
            suffix = CommonConstants.EMPTY;
        }
        
        int truncateLength = maxLength - suffix.length();
        if (truncateLength <= 0) {
            return suffix.substring(0, maxLength);
        }
        
        return str.substring(0, truncateLength) + suffix;
    }
    
    // ==================== 连接方法 ====================
    
    /**
     * 使用指定分隔符连接字符串数组
     * 
     * @param separator 分隔符
     * @param elements 字符串数组
     * @return 连接后的字符串
     */
    public static String join(String separator, String... elements) {
        if (elements == null || elements.length == 0) {
            return CommonConstants.EMPTY;
        }
        
        if (separator == null) {
            separator = CommonConstants.EMPTY;
        }
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < elements.length; i++) {
            if (i > 0) {
                sb.append(separator);
            }
            if (elements[i] != null) {
                sb.append(elements[i]);
            }
        }
        return sb.toString();
    }
    
    /**
     * 使用指定分隔符连接集合中的元素
     * 
     * @param separator 分隔符
     * @param elements 元素集合
     * @return 连接后的字符串
     */
    public static String join(String separator, Collection<?> elements) {
        if (elements == null || elements.isEmpty()) {
            return CommonConstants.EMPTY;
        }
        
        if (separator == null) {
            separator = CommonConstants.EMPTY;
        }
        
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (Object element : elements) {
            if (!first) {
                sb.append(separator);
            }
            if (element != null) {
                sb.append(element.toString());
            }
            first = false;
        }
        return sb.toString();
    }
    
    // ==================== 格式验证方法 ====================
    
    /**
     * 验证是否为有效的手机号
     * 
     * @param mobile 手机号
     * @return 是否有效
     */
    public static boolean isValidMobile(String mobile) {
        return isNotBlank(mobile) && MOBILE_PATTERN.matcher(mobile).matches();
    }
    
    /**
     * 验证是否为有效的邮箱地址
     * 
     * @param email 邮箱地址
     * @return 是否有效
     */
    public static boolean isValidEmail(String email) {
        return isNotBlank(email) && EMAIL_PATTERN.matcher(email).matches();
    }
    
    /**
     * 验证是否为有效的身份证号
     * 
     * @param idCard 身份证号
     * @return 是否有效
     */
    public static boolean isValidIdCard(String idCard) {
        return isNotBlank(idCard) && ID_CARD_PATTERN.matcher(idCard).matches();
    }
    
    /**
     * 判断字符串是否包含中文字符
     * 
     * @param str 字符串
     * @return 是否包含中文
     */
    public static boolean containsChinese(String str) {
        return isNotBlank(str) && CHINESE_PATTERN.matcher(str).find();
    }
    
    // ==================== 编码方法 ====================
    
    /**
     * 获取字符串的UTF-8字节数组
     * 
     * @param str 字符串
     * @return UTF-8字节数组
     */
    public static byte[] getUtf8Bytes(String str) {
        return str == null ? new byte[0] : str.getBytes(StandardCharsets.UTF_8);
    }
    
    /**
     * 从UTF-8字节数组创建字符串
     * 
     * @param bytes UTF-8字节数组
     * @return 字符串
     */
    public static String fromUtf8Bytes(byte[] bytes) {
        return bytes == null ? CommonConstants.EMPTY : new String(bytes, StandardCharsets.UTF_8);
    }
    
    // ==================== 脱敏方法 ====================
    
    /**
     * 手机号脱敏
     * 
     * @param mobile 手机号
     * @return 脱敏后的手机号
     */
    public static String maskMobile(String mobile) {
        if (!isValidMobile(mobile)) {
            return mobile;
        }
        return mobile.substring(0, 3) + "****" + mobile.substring(7);
    }
    
    /**
     * 邮箱脱敏
     * 
     * @param email 邮箱
     * @return 脱敏后的邮箱
     */
    public static String maskEmail(String email) {
        if (!isValidEmail(email)) {
            return email;
        }
        
        int atIndex = email.indexOf('@');
        if (atIndex <= 1) {
            return email;
        }
        
        String prefix = email.substring(0, 1);
        String suffix = email.substring(atIndex);
        return prefix + "***" + suffix;
    }
    
    /**
     * 身份证号脱敏
     * 
     * @param idCard 身份证号
     * @return 脱敏后的身份证号
     */
    public static String maskIdCard(String idCard) {
        if (!isValidIdCard(idCard)) {
            return idCard;
        }
        return idCard.substring(0, 6) + "********" + idCard.substring(14);
    }
}
